From 88b78953b68b01d9ac2f46b088322e4188fb9f38 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Mon, 11 Oct 2010 00:23:40 +0200 Subject: [PATCH] GtkContainer: Add method to get the GtkWidgetPath for a child. This is now used throughout in order to have the full path for a given widget, including intermediate named regions, the default implementation just returns the GtkContainer's path copy, no intermediate regions between. --- gtk/gtkcontainer.c | 22 +++++++++ gtk/gtkcontainer.h | 5 ++ gtk/gtkstylecontext.c | 21 +++++---- gtk/gtkwidget.c | 105 ++++++++++++++++-------------------------- gtk/gtkwidgetpath.c | 15 ++++++ gtk/gtkwidgetpath.h | 2 + 6 files changed, 95 insertions(+), 75 deletions(-) diff --git a/gtk/gtkcontainer.c b/gtk/gtkcontainer.c index a37e361d65..8c09ba2514 100644 --- a/gtk/gtkcontainer.c +++ b/gtk/gtkcontainer.c @@ -334,6 +334,9 @@ static void gtk_container_adjust_size_allocation (GtkWidget *widget, static gchar* gtk_container_child_default_composite_name (GtkContainer *container, GtkWidget *child); +static GtkWidgetPath * gtk_container_real_get_path_for_child (GtkContainer *container, + GtkWidget *child); + /* GtkBuildable */ static void gtk_container_buildable_init (GtkBuildableIface *iface); static void gtk_container_buildable_add_child (GtkBuildable *buildable, @@ -465,6 +468,7 @@ gtk_container_class_init (GtkContainerClass *class) class->set_focus_child = gtk_container_real_set_focus_child; class->child_type = NULL; class->composite_name = gtk_container_child_default_composite_name; + class->get_path_for_child = gtk_container_real_get_path_for_child; g_object_class_install_property (gobject_class, PROP_RESIZE_MODE, @@ -2207,6 +2211,13 @@ gtk_container_get_all_children (GtkContainer *container) return children; } +static GtkWidgetPath * +gtk_container_real_get_path_for_child (GtkContainer *container, + GtkWidget *child) +{ + return gtk_widget_path_copy (gtk_widget_get_path (GTK_WIDGET (container))); +} + static gboolean gtk_container_focus (GtkWidget *widget, GtkDirectionType direction) @@ -3220,3 +3231,14 @@ _gtk_container_get_reallocate_redraws (GtkContainer *container) { return container->priv->reallocate_redraws; } + +GtkWidgetPath * +gtk_container_get_path_for_child (GtkContainer *container, + GtkWidget *child) +{ + g_return_val_if_fail (GTK_IS_CONTAINER (container), NULL); + g_return_val_if_fail (GTK_IS_WIDGET (child), NULL); + g_return_val_if_fail (container == (GtkContainer *) gtk_widget_get_parent (child), NULL); + + return GTK_CONTAINER_GET_CLASS (container)->get_path_for_child (container, child); +} diff --git a/gtk/gtkcontainer.h b/gtk/gtkcontainer.h index f469d89eba..94a8502c8f 100644 --- a/gtk/gtkcontainer.h +++ b/gtk/gtkcontainer.h @@ -88,6 +88,8 @@ struct _GtkContainerClass guint property_id, GValue *value, GParamSpec *pspec); + GtkWidgetPath * (*get_path_for_child) (GtkContainer *container, + GtkWidget *child); /* Padding for future expansion */ void (*_gtk_reserved1) (void); @@ -228,6 +230,9 @@ void _gtk_container_set_need_resize (GtkContainer *container, gboolean need_resize); gboolean _gtk_container_get_reallocate_redraws (GtkContainer *container); +GtkWidgetPath * gtk_container_get_path_for_child (GtkContainer *container, + GtkWidget *child); + G_END_DECLS #endif /* __GTK_CONTAINER_H__ */ diff --git a/gtk/gtkstylecontext.c b/gtk/gtkstylecontext.c index 69e7797d89..13d15f9179 100644 --- a/gtk/gtkstylecontext.c +++ b/gtk/gtkstylecontext.c @@ -524,11 +524,14 @@ rebuild_properties (GtkStyleContext *context) priv = context->priv; list = priv->providers; + gtk_style_set_clear (priv->store); + + if (!priv->widget_path) + return; + if (priv->screen) global_list = g_object_get_qdata (G_OBJECT (priv->screen), provider_list_quark); - gtk_style_set_clear (priv->store); - while ((elem = find_next_candidate (list, global_list)) != NULL) { GtkStyleProviderData *data; @@ -566,11 +569,13 @@ rebuild_icon_factories (GtkStyleContext *context) GList *elem, *list, *global_list = NULL; priv = context->priv; - g_slist_foreach (priv->icon_factories, (GFunc) g_object_unref, NULL); g_slist_free (priv->icon_factories); priv->icon_factories = NULL; + if (!priv->widget_path) + return; + list = priv->providers_last; if (priv->screen) @@ -948,10 +953,9 @@ gtk_style_context_set_path (GtkStyleContext *context, } if (path) - { - priv->widget_path = gtk_widget_path_copy (path); - gtk_style_context_invalidate (context); - } + priv->widget_path = gtk_widget_path_copy (path); + + gtk_style_context_invalidate (context); } G_CONST_RETURN GtkWidgetPath * @@ -1953,9 +1957,6 @@ gtk_style_context_invalidate (GtkStyleContext *context) if (priv->invalidating_context) return; - if (!priv->widget_path) - return; - priv->invalidating_context = TRUE; rebuild_properties (context); diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index 3dfbc6ce2d..4da12a1639 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -374,6 +374,9 @@ struct _GtkWidgetPrivate /* The widget's parent. */ GtkWidget *parent; + + /* Widget's path for styling */ + GtkWidgetPath *path; }; enum { @@ -7229,6 +7232,18 @@ gtk_widget_is_sensitive (GtkWidget *widget) return widget->priv->sensitive && widget->priv->parent_sensitive; } +static void +_gtk_widget_update_path (GtkWidget *widget) +{ + if (widget->priv->path) + { + gtk_widget_path_free (widget->priv->path); + widget->priv->path = NULL; + } + + gtk_widget_get_path (widget); +} + /** * gtk_widget_set_parent: * @widget: a #GtkWidget @@ -7326,11 +7341,8 @@ gtk_widget_set_parent (GtkWidget *widget, quark_style_context); if (context) { - GtkWidgetPath *path; - - path = gtk_widget_get_path (widget); - gtk_style_context_set_path (context, path); - gtk_widget_path_free (path); + _gtk_widget_update_path (widget); + gtk_style_context_set_path (context, widget->priv->path); gtk_style_context_set_screen (context, gtk_widget_get_screen (widget)); @@ -8139,7 +8151,10 @@ reset_style_recurse (GtkWidget *widget, gpointer data) context = g_object_get_qdata (G_OBJECT (widget), quark_style_context); if (context) - gtk_style_context_invalidate (context); + { + _gtk_widget_update_path (widget); + gtk_style_context_set_path (context, widget->priv->path); + } if (GTK_IS_CONTAINER (widget)) gtk_container_forall (GTK_CONTAINER (widget), @@ -13267,71 +13282,34 @@ _gtk_widget_set_height_request_needed (GtkWidget *widget, GtkWidgetPath * gtk_widget_get_path (GtkWidget *widget) { - GtkStyleContext *context; - GtkWidgetPath *path; - GtkWidget *parent; - g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); - parent = widget->priv->parent; - - path = gtk_widget_path_new (); - gtk_widget_path_prepend_type (path, G_OBJECT_TYPE (widget)); - - if (widget->priv->name) - gtk_widget_path_iter_set_name (path, 0, widget->priv->name); - - context = g_object_get_qdata (G_OBJECT (widget), - quark_style_context); - - if (context) + if (!widget->priv->path) { - GList *list, *l; - - list = l = gtk_style_context_list_regions (context); - - while (l) - { - GtkRegionFlags flags; - const gchar *region_name; - - region_name = l->data; - l = l->next; - - gtk_style_context_has_region (context, region_name, &flags); - gtk_widget_path_iter_add_region (path, 0, region_name, flags); - } - - g_list_free (list); + GtkWidget *parent; + guint pos; - list = l = gtk_style_context_list_classes (context); + parent = widget->priv->parent; - while (l) + if (parent) + widget->priv->path = gtk_container_get_path_for_child (GTK_CONTAINER (parent), widget); + else { - const gchar *class_name; - - class_name = l->data; - l = l->next; - - gtk_widget_path_iter_add_class (path, 0, class_name); + /* Widget is either toplevel or unparented, treat both + * as toplevels style wise, since there are situations + * where style properties might be retrieved on that + * situation. + */ + widget->priv->path = gtk_widget_path_new (); } - g_list_free (list); - } - - while (parent) - { - guint position; - - position = gtk_widget_path_prepend_type (path, G_OBJECT_TYPE (parent)); - - if (parent->priv->name) - gtk_widget_path_iter_set_name (path, position, parent->priv->name); + pos = gtk_widget_path_append_type (widget->priv->path, G_OBJECT_TYPE (widget)); - parent = parent->priv->parent; + if (widget->priv->name) + gtk_widget_path_iter_set_name (widget->priv->path, pos, widget->priv->name); } - return path; + return widget->priv->path; } static void @@ -13355,8 +13333,6 @@ gtk_widget_get_style_context (GtkWidget *widget) if (G_UNLIKELY (!context)) { - GtkWidgetPath *path; - context = g_object_new (GTK_TYPE_STYLE_CONTEXT, "direction", gtk_widget_get_direction (widget), NULL); @@ -13371,9 +13347,8 @@ gtk_widget_get_style_context (GtkWidget *widget) gtk_style_context_set_screen (context, gtk_widget_get_screen (widget)); - path = gtk_widget_get_path (widget); - gtk_style_context_set_path (context, path); - gtk_widget_path_free (path); + _gtk_widget_update_path (widget); + gtk_style_context_set_path (context, widget->priv->path); } return context; diff --git a/gtk/gtkwidgetpath.c b/gtk/gtkwidgetpath.c index 933a2dc0c7..c6cfbb5c81 100644 --- a/gtk/gtkwidgetpath.c +++ b/gtk/gtkwidgetpath.c @@ -128,6 +128,21 @@ gtk_widget_path_prepend_type (GtkWidgetPath *path, g_return_val_if_fail (path != NULL, 0); g_return_val_if_fail (g_type_is_a (type, GTK_TYPE_WIDGET), 0); + new.type = type; + g_array_prepend_val (path->elems, new); + + return 0; +} + +guint +gtk_widget_path_append_type (GtkWidgetPath *path, + GType type) +{ + GtkPathElement new = { 0 }; + + g_return_val_if_fail (path != NULL, 0); + g_return_val_if_fail (g_type_is_a (type, GTK_TYPE_WIDGET), 0); + new.type = type; g_array_append_val (path->elems, new); diff --git a/gtk/gtkwidgetpath.h b/gtk/gtkwidgetpath.h index 234f79b937..4e5c4769cb 100644 --- a/gtk/gtkwidgetpath.h +++ b/gtk/gtkwidgetpath.h @@ -35,6 +35,8 @@ void gtk_widget_path_free (GtkWidgetPath *path); guint gtk_widget_path_length (const GtkWidgetPath *path); +guint gtk_widget_path_append_type (GtkWidgetPath *path, + GType type); guint gtk_widget_path_prepend_type (GtkWidgetPath *path, GType type); -- 2.30.2